package com.nuoyuan.wx.common.utils;

import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Decoder;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * @Author linus
 * @Date 9/17/18 : 22 : 59
 * @ProjectName otc-backend
 * @Package com.shanlin.coinfairserver.common.util
 * @Description
 */
public class RSAUtil{
    public static final String KEY_ALGORITHM="RSA";
    public static final String SIGNATURE_ALGORITHM="MD5withRSA";
    private static final int KEY_SIZE=1024;
    private static final String PUBLIC_KEY="RSAPublicKey";
    private static final String PRIVATE_KEY="RSAPrivateKey";

    public static String str_priK = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALhFYcHEmmHs6z4JOhuEsDf1fKoaPhkxrdj4OXlOepwO/+CoLkw7CinbsJ+m0p4Bd2PtKpLJD3MnJd7AJ/WBaW5sdF3eK1u3NC1X8Z+bU2p2HR64+exWzXGtQS0k7KOsvf2D00zzsCTXF9315o1enyEOOEkrNmrYuJtO7MxsK3ODAgMBAAECgYEAjJl75pIxTaitMa9uo9KRdpEb5tqRKT4LrPJxQArOaMbVHECW2tltftS+poJuT9tEkn1Cr68z16Q2NAkgNCXjH+9EwIg9b7n+T0dF9WhaI9XfY4gdNTAVmzvyeq6VlLx9JPfxX5fcwJxr8RR3toBDz5cz0lny+KloidMKyE2C8TECQQDkpBsg8JQ1g3VDT/vqFgpKNkYAUoJv3BEXUVTZhFnw2nPvUZLR/TzivD8/a31crSC7I9ofpcnhj2EyHVAqXXqZAkEAzlIaKDOTjUU5SdJZDcGfDyjoB/dmJeX1jgn7Vk4v7m3T63RSTqVsjbGn0CvejF/q28NOuh4L37E5mk0oJHFsewJAWvf8Hzf5D+2Uy0pYhYNtZqd/ZINviEf7uNZQNxcUneKcu/wtuUTTY7bYR0hiIWx0mGCkWXEiCI9+cWz+R0zYCQJBAJvK9UNsBrwDDIpI0sQHc6MP4X26e6Ccb3ps4SO/cIQa3I4LzObkFP89qhkQN0FKYF7HsNfrPk4QVg3Eu04hc6cCQAenZwFPdg5lUwKGTPhUziUxXPUhtUYpiCkUgSFbGOwHGS2xzxDLaGUAcDIvHTKjh5oDFtnXQMao6BW6XHbkcAM=";

    public static String str_pubK = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4RWHBxJph7Os+CTobhLA39Xyq\n"+
            "Gj4ZMa3Y+Dl5TnqcDv/gqC5MOwop27CfptKeAXdj7SqSyQ9zJyXewCf1gWlubHRd\n"+
            "3itbtzQtV/Gfm1Nqdh0euPnsVs1xrUEtJOyjrL39g9NM87Ak1xfd9eaNXp8hDjhJ\n"+
            "KzZq2LibTuzMbCtzgwIDAQAB";
    /**
     * 使用getPublicKey得到公钥,返回类型为PublicKey
     * @param base64 String to PublicKey
     * @throws Exception
     */
    public static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }
    /**
     * 转换私钥
     * @param base64 String to PrivateKey
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    //***************************签名和验证*******************************
    public static byte[] sign(byte[] data) throws Exception{
        PrivateKey priK = getPrivateKey(str_priK);
        Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
        sig.initSign(priK);
        sig.update(data);
        return sig.sign();
    }

    public static boolean verify(byte[] data,byte[] sign) throws Exception{
        PublicKey pubK = getPublicKey(str_pubK);
        Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
        sig.initVerify(pubK);
        sig.update(data);
        return sig.verify(sign);
    }

    //************************加密解密**************************
    public static byte[] encrypt(byte[] bt_plaintext)throws Exception{
        PublicKey publicKey = getPublicKey(str_pubK);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] bt_encrypted = cipher.doFinal(bt_plaintext);
        return bt_encrypted;
    }

    public static byte[] decrypt(byte[] bt_encrypted)throws Exception{
        PrivateKey privateKey = getPrivateKey(str_priK);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] bt_original = cipher.doFinal(bt_encrypted);
        return bt_original;
    }
    //********************main函数：加密解密和签名验证*********************
    public static void main(String[] args) throws Exception {
        String str_plaintext = "这是一段用来测试密钥转换的明文";
        System.err.println("明文："+str_plaintext);
        byte[] bt_cipher = encrypt(str_plaintext.getBytes());
        System.out.println("加密后："+Base64.encodeBase64String(bt_cipher));

        byte[] bt_original = decrypt(bt_cipher);
        String str_original = new String(bt_original);
        System.out.println("解密结果:"+str_original);

        String str="被签名的内容";
        System.err.println("\n原文:"+str);
        byte[] signature=sign(str.getBytes());
        System.out.println("产生签名："+Base64.encodeBase64String(signature));
        boolean status=verify(str.getBytes(), signature);
        System.out.println("验证情况："+status);
    }

}